#include "rabbitvcsmenuhelper.h"
#include <QProcess>

#include <QAction>
#include <QMenu>

#include <QFileInfo>

#include <QMessageBox>

#include <QDebug>

#define VCS_SVN 0
#define VCS_GIT 1
#define VCS_MERCURIAL 3
#define VCS_HG 4

QString create_path_revision_string(const QString &path, const QString &reversion)
{
    if (!reversion.isEmpty()) {
        return path + "@" + reversion;
    } else {
        return path;
    }
}

static QAction *createSeparator()
{
    auto separator = new QAction();
    separator->setSeparator(true);
    return separator;
}

static void executeCommand(const QString &command, const QStringList &paths)
{
    QProcess p;
    p.setProgram("rabbitvcs");
    p.setArguments(QStringList()<<command<<paths);
    p.startDetached();
    p.waitForFinished();
}

// command util
void doCheckOut(const QStringList &paths)
{
    executeCommand("checkout", paths);
}

void doUpdate(const QStringList &paths)
{
    executeCommand("update", paths);
}

void doCommit(const QStringList &paths)
{
    executeCommand("commit", paths);
}

void doAdd(const QStringList &paths)
{
    executeCommand("add", paths);
}

void doCheckForModification(const QStringList &paths)
{
    executeCommand("checkmods", paths);
}

void doDelete(const QStringList &paths)
{
    executeCommand("delete", paths);
}

void doRevert(const QStringList &paths)
{
    executeCommand("revert", paths);
}

void doDiff(const QStringList &paths)
{
    executeCommand("diff", paths);
}

void doDiffMultiple(const QStringList &paths)
{
    doDiff(paths);
}

void doDiffPreviousReversion(const QStringList &paths, const QString &vcs)
{
    if (vcs == "svn") {
        auto pathrev1 = create_path_revision_string(paths.first(), "base");
        auto pathrev2 = create_path_revision_string(paths.first(), "working");
        executeCommand("diff", QStringList()<<"-s"<<pathrev1<<pathrev2);
        /*
         *  pathrev1 = helper.create_path_revision_string(self.paths[0], "base")
        pathrev2 = helper.create_path_revision_string(self.paths[0], "working")

        proc = helper.launch_ui_window("diff", [
            "-s",
            pathrev1,
            pathrev2
        ])
         */
    }
}

void doCompareTool(const QStringList &paths)
{
    auto pathrev1 = create_path_revision_string(paths.first(), "base");
    auto pathrev2 = create_path_revision_string(paths.first(), "working");
    executeCommand("diff", QStringList()<<"-s"<<pathrev1<<pathrev2);
    /*
     * pathrev1 = helper.create_path_revision_string(self.paths[0], "base")
        pathrev2 = helper.create_path_revision_string(self.paths[0], "working")

        proc = helper.launch_ui_window("diff", [
            "-s",
            pathrev1,
            pathrev2
        ])
     */
}

void doCompareToolMultiple(const QStringList &paths)
{
    executeCommand("diff", QStringList()<<"-s"<<paths);
}

void doCompareToolPreviousReversion(const QStringList &paths, const QString &vcs)
{
    QMessageBox::warning(0, 0, "not support now");
    // FIXME:
    /*
     * guess = self.vcs_client.guess(self.paths[0])
        if guess["vcs"] == rabbitvcs.vcs.VCS_SVN:
            previous_revision_number = self.vcs_client.svn().get_revision(self.paths[0]) - 1

            pathrev1 = helper.create_path_revision_string(self.vcs_client.svn().get_repo_url(self.paths[0]), previous_revision_number)
            pathrev2 = helper.create_path_revision_string(self.paths[0], "working")

            proc = helper.launch_ui_window("diff", [
                "-s",
                pathrev1,
                pathrev2,
                "--vcs=%s" % rabbitvcs.vcs.VCS_SVN
            ])
     */
}

void doShowChanges(const QStringList &paths)
{
    auto pathrev1 = create_path_revision_string(paths.first(), nullptr);
    auto pathrev2 = pathrev1;
    if (paths.length() == 2) {
        pathrev2 = create_path_revision_string(paths.at(1), nullptr);
    }
    executeCommand("changes", QStringList()<<pathrev1<<pathrev2);
    /*
     * def show_changes(self, widget, data1=None, data2=None):
        pathrev1 = helper.create_path_revision_string(self.paths[0])
        pathrev2 = pathrev1
        if len(self.paths) == 2:
            pathrev2 = helper.create_path_revision_string(self.paths[1])

        proc = helper.launch_ui_window("changes", [pathrev1, pathrev2])
        self.caller.rescan_after_process_exit(proc, self.paths)
     */
}

void doShowLog(const QStringList &paths)
{
    executeCommand("log", paths);
}

void doRename(const QStringList &paths)
{
    executeCommand("rename", paths);
}

void doCreatePatch(const QStringList &paths)
{
    executeCommand("createpatch", paths);
}

void doApplyPatch(const QStringList &paths)
{
    executeCommand("applypatch", paths);
}

void doProperties(const QStringList &paths)
{
    executeCommand("property_editor", paths);
}

void doAbout()
{
    executeCommand("about", QStringList());
}

void doSettings(const QStringList &paths)
{
    if (paths.length() == 1 && QFileInfo(paths.first()).isDir()) {
        executeCommand("settings", QStringList()<<paths.first());
    } else {
        executeCommand("settings", QStringList());
    }
}

void doIgnoreByFileName(const QStringList &paths)
{
    //FIXME
}

void doIgnoreByFileExtension(const QStringList &paths)
{
    //FIXME
}

void doGetLock(const QStringList &paths)
{
    executeCommand("lock", paths);
}

void doBranchTag(const QStringList &paths)
{
    executeCommand("branch", paths);
}

void doSwitch(const QStringList &paths)
{
    executeCommand("switch", paths);
}

void doMerge(const QStringList &paths)
{
    executeCommand("merge", paths);
}

void doImport(const QStringList &paths)
{
    executeCommand("import", paths);
}

void doExport(const QStringList &paths)
{
    executeCommand("export", paths);
}

void doSVNExport(const QStringList &paths)
{
    executeCommand("export", QStringList()<<"--vcs=svn"<<paths);
}

void doGitExport(const QStringList &paths)
{
    executeCommand("export", QStringList()<<"--vcs=git"<<paths);
}

void doUpdateToReversion(const QStringList &paths)
{
    executeCommand("updateto", paths);
}

void doMarkResolved(const QStringList &paths)
{
    executeCommand("markresolved", paths);
}

void doAnnotate(const QStringList &paths)
{
    executeCommand("annotate", paths);
}

void doUnlock(const QStringList &paths)
{
    executeCommand("unlock", paths);
}

void doCreateRepository(const QStringList &paths)
{
    executeCommand("create", QStringList()<<"--vcs"<<"svn"<<paths);
}

void doRelocate(const QStringList &paths)
{
    executeCommand("relocate", paths);
}

void doCleanUp(const QStringList &paths)
{
    executeCommand("cleanup", paths);
}

void doRestore(const QStringList &paths, bool isGit)
{
    if (isGit) {
        executeCommand("checkout", QStringList()<<"-q"<<"--vcs"<<"git"<<paths);
    } else {
        executeCommand("update", paths);
    }
}

void doClone(const QStringList &paths)
{
    executeCommand("clone", QStringList()<<paths.first());
}

void doPush(const QStringList &paths)
{
    executeCommand("push", paths);
}

void doBranches(const QStringList &paths)
{
    executeCommand("branches", QStringList()<<paths.first());
}

void doTags(const QStringList &paths)
{
    executeCommand("tags", QStringList()<<paths.first());
}

void doRemotes(const QStringList &paths)
{
    executeCommand("remotes", QStringList()<<paths.first());
}

void doClean(const QStringList &paths)
{
    executeCommand("clean", QStringList()<<paths.first());
}

void doReset(const QStringList &paths)
{
    executeCommand("reset", QStringList()<<paths.first());
}

void doStage(const QStringList &paths)
{
    executeCommand("stage", QStringList()<<paths.first());
}

void doUnstage(const QStringList &paths)
{
    executeCommand("unstage", QStringList()<<paths.first());
}

void doEditConflicts(const QStringList &paths)
{
    executeCommand("editconflicts", QStringList()<<paths.first());
}

QStringList getTrueLists(const QString &conditions)
{
    QStringList result;
    auto list = conditions.split(",");
    for (QString item : list) {
        if (item.contains("true")) {
            item.remove("\"");
            item.remove("true");
            item.remove(" ");
            item.remove(":");
            result<<item;
        }
    }
    return result;
}

QMenu *getDiffSubMenu(const QStringList &paths, const QStringList &trueList)
{
    int length = paths.length();
    bool is_in_a_or_a_working_copy = trueList.contains("is_in_a_or_a_working_copy");
    bool is_modified = trueList.contains("is_modified");
    bool has_modified = trueList.contains("has_modified");
    bool is_conflicted = trueList.contains("is_conflicted");
    bool has_conflicted = trueList.contains("has_conflicted");
    bool is_versioned = trueList.contains("is_versioned");
    bool is_svn = trueList.contains("is_svn");
    bool canDiff = length == 1 && is_in_a_or_a_working_copy && (is_modified || has_modified || is_conflicted || has_conflicted);
    bool canDiffMultiple = length == 2 && is_versioned && is_in_a_or_a_working_copy;;
    bool canCompareTool = canDiff;
    bool canCompareToolPreviousReversion = is_svn && is_in_a_or_a_working_copy && length == 1;
    bool canCompareToolMultiple = canDiffMultiple;
    bool canShowChanges = is_in_a_or_a_working_copy && is_versioned && (length == 1 || length == 2);
    auto menu = new QMenu;
    auto diifAction = menu->addAction(QObject::tr("Diff"), [=]{
        doDiff(paths);
    });
    diifAction->setVisible(canDiff);
    auto diffMultipleAction = menu->addAction(QObject::tr("Diff Multiple"), [=]{
        doDiffMultiple(paths);
    });
    diffMultipleAction->setVisible(canDiffMultiple);
    auto compareToolAction = menu->addAction(QObject::tr("Compare Tool"), [=]{
        doCompareTool(paths);
    });
    compareToolAction->setVisible(canCompareTool);
    auto compareToolPreRevAction = menu->addAction(QObject::tr("Compare Tool Previous Reversion"), [=]{
        doCompareToolPreviousReversion(paths, "svn");
    });
    compareToolPreRevAction->setVisible(canCompareToolPreviousReversion);
    auto compareToolMultipleAction = menu->addAction(QObject::tr("Compare Tool Multiple"), [=]{
        doCompareToolMultiple(paths);
    });
    compareToolMultipleAction->setVisible(canCompareToolMultiple);
    auto showChangesAction = menu->addAction(QObject::tr("Show Changes"), [=]{
        doShowChanges(paths);
    });
    showChangesAction->setVisible(canShowChanges);
    /*
     * (MenuDiff, None),
                    (MenuDiffPrevRev, None),
                    (MenuDiffMultiple, None),
                    (MenuCompareTool, None),
                    (MenuCompareToolPrevRev, None),
                    (MenuCompareToolMultiple, None),
                    (MenuShowChanges, None),
     */
    return menu;
}

QMenu *getFileContextMenu(const QStringList &paths, const QStringList &trueList)
{
    /*
     * (MenuDiff, None),
        (MenuCompareTool, None),
        (MenuUnlock, None),
        (MenuShowLog, None),
        (MenuOpen, None),
        (MenuBrowseTo, None),
        (MenuDelete, None),
        (MenuRevert, None),
        (MenuRestore, None),
        (MenuEditConflicts, None),
        (MenuMarkResolved, None),
        (MenuCreatePatch, None),
        (MenuAdd, None),
        (MenuStage, None),
        (MenuUnstage, None),
        (MenuAddToIgnoreList, ignore_items)
     */
    auto menu = new QMenu;
    auto compareToolAction = menu->addAction(QObject::tr("Compare Tool"), [=]{

    });
    auto unlockAction = menu->addAction(QObject::tr("Unlock"), [=]{

    });
    auto showLogAction = menu->addAction(QObject::tr("Show Log"), [=]{

    });
    auto openAction = menu->addAction(QObject::tr("Open"), [=]{

    });
    auto browseToAction = menu->addAction(QObject::tr("Browse To"), [=]{

    });
    auto deleteAction = menu->addAction(QObject::tr("Delete"), [=]{

    });
    auto revertAction = menu->addAction(QObject::tr("Revert"), [=]{

    });
    auto restoreAction = menu->addAction(QObject::tr("Restore"), [=]{

    });
    auto editConflictsAction = menu->addAction(QObject::tr("Edit Conflicts"), [=]{

    });
    auto markResolvedAction = menu->addAction(QObject::tr("Mark Resolved"), [=]{

    });
    auto createPatchAction = menu->addAction(QObject::tr("Create Patch"), [=]{

    });
    auto addAction = menu->addAction(QObject::tr("Add"), [=]{

    });
    auto stageAction = menu->addAction(QObject::tr("Stage"), [=]{

    });
    auto unstageAction = menu->addAction(QObject::tr("Unstage"), [=]{

    });
    auto addToIgnoreListAction = menu->addAction(QObject::tr("Add to Ignore List"), [=]{

    });
    return menu;
}

QMenu *getMainContextSubMenu(int vcs_module, const QStringList &paths, const QStringList &trueList)
{
    QMenu *menu = nullptr;

    int length = paths.length();
    bool is_svn = trueList.contains("is_svn");
    bool is_git = trueList.contains("is_git");
    bool is_mercurial = trueList.contains("is_mercurial");
    bool is_dir = trueList.contains("is_dir");
    bool is_file = trueList.contains("is_file");
    bool exists = trueList.contains("exists");
    bool is_working_copy = trueList.contains("is_working_copy");
    bool is_in_a_or_a_working_copy = trueList.contains("is_in_a_or_a_working_copy");
    bool is_versioned = trueList.contains("is_versioned");
    bool is_normal = trueList.contains("is_normal");
    bool is_added = trueList.contains("is_added");
    bool is_modified = trueList.contains("is_modified");
    bool is_deleted = trueList.contains("is_deleted");
    bool is_ignored = trueList.contains("is_ignored");
    bool is_locked = trueList.contains("is_locked");
    bool is_missing = trueList.contains("is_missing");
    bool is_conflicted = trueList.contains("is_conflicted");
    bool is_obstructed = trueList.contains("is_obstructed");
    bool has_unversioned = trueList.contains("has_unversioned");
    bool has_added = trueList.contains("has_added");
    bool has_modified = trueList.contains("has_modified");
    bool has_deleted = trueList.contains("has_deleted");
    bool has_ignored = trueList.contains("has_ignored");
    bool has_missing = trueList.contains("has_missing");
    bool has_conflicted = trueList.contains("has_conflicted");
    bool has_obstructed = trueList.contains("has_obstructed");

    auto canCheckoutFunc = [&]()->bool{
        if (length == 1) {
            if (is_git) {
                return is_in_a_or_a_working_copy && is_versioned;
            } else {
                return is_dir && !is_working_copy;
            }
        }
        return false;
    };
    bool canCheckout = canCheckoutFunc();

    bool canUpdate = is_in_a_or_a_working_copy && is_versioned && !is_added;

    auto canCommitFunc = [&]()->bool{
            if (is_svn || is_git || is_mercurial) {
                if (is_in_a_or_a_working_copy) {
                    if (is_added || is_modified || is_deleted || !is_versioned) {
                        return true;
                    } else {
                        if (is_dir) {return true;}
                    }
                }
            }
            return false;
        };
    bool canCommit = canCommitFunc();

    bool canDiffMenu = is_in_a_or_a_working_copy;

    bool canDiffMultiple = length == 2 && is_versioned && is_in_a_or_a_working_copy;

    bool compareToolMultiple = canDiffMultiple;

    bool canDiff = length == 1 && is_in_a_or_a_working_copy && (is_modified || has_modified || is_conflicted || has_conflicted);

    bool canDiffPreviousReversion = is_svn && is_in_a_or_a_working_copy && length == 1;

    bool canCompareTool = canDiff;

    bool canCompareToolPreviousReversion = is_svn && is_in_a_or_a_working_copy && length == 1;

    bool canShowChanges = is_in_a_or_a_working_copy && is_versioned && (length == 1 || length == 2);

    bool canShowLog = length == 1 && is_in_a_or_a_working_copy && is_versioned && !is_added;

    auto canAddFunc = [=]()->bool{
        if (!is_svn) {
            return false;
        }

        if (is_dir && is_in_a_or_a_working_copy) {
            return true;
        } else if (!is_dir && is_in_a_or_a_working_copy && !is_versioned) {
            return true;
        }

        return false;
    };
    bool canAdd = canAddFunc();

    bool canCheckForModification = is_working_copy || is_versioned;

    bool canRename = length == 1 && is_in_a_or_a_working_copy && !is_working_copy && is_versioned;

    bool canDelete = (exists || is_versioned) && !is_deleted;

    auto canRevertFunc = [&]()->bool{
        if (is_in_a_or_a_working_copy) {
            if (is_added || is_modified || is_deleted) {
                return true;
            } else {
                if (is_dir && (has_added || has_modified || has_deleted || has_missing))
                    return true;
            }
        }
        return false;
    };
    bool canRevert = canRevertFunc();

    bool canAnnotate = length == 1 && !is_dir && is_in_a_or_a_working_copy && is_versioned && !is_added;

    bool canProperties = length == 1 && is_in_a_or_a_working_copy && is_versioned;

    auto canCreatePatchFunc = [&]()->bool{
        if (is_in_a_or_a_working_copy) {
            if (is_added || is_modified || is_deleted || !is_versioned) {
                return true;
            } else {
                if (is_dir && (has_added || has_modified || has_deleted || has_missing)) {
                    return true;
                }
            }
        }
        return false;
    };
    bool canCreatePatch = canCreatePatchFunc();

    bool canApplyPatch = is_in_a_or_a_working_copy;

    bool canAddToIgnoreList = is_in_a_or_a_working_copy && !is_versioned;

    bool canIgnoreByFileName = is_in_a_or_a_working_copy && !is_versioned;

    bool canIgnoreByFileExtension = canIgnoreByFileName;

    bool canRefreshStatus = true;

    bool canGetLock = is_versioned;

    bool canBranchTag = canGetLock;

    bool canRelocate = canGetLock;

    bool canSwitch = canGetLock;

    bool canMerge = canGetLock;

    bool canImport = length == 1 && !is_in_a_or_a_working_copy;

    bool canExport = length == 1;

    bool canSVNExport = canExport;

    bool canGitExport = canExport;

    bool canUpdateToReversion = length == 1 && is_versioned && is_in_a_or_a_working_copy;

    bool canMarkResolved = is_in_a_or_a_working_copy && is_versioned && is_conflicted;

    bool canCreateRepository = length == 1 && !is_in_a_or_a_working_copy;

    bool canUnlock = is_in_a_or_a_working_copy && is_versioned && (is_dir || is_locked);

    bool canCleanUp = is_versioned;

    bool canBrowseTo = exists;

    bool canOpen = is_file;

    bool canRestore = has_missing;

    bool canRepoBrowser = true;

    bool canRabbitVCS = false;

    bool canRabbitVCS_SVN = is_svn || !is_in_a_or_a_working_copy;

    bool canRabbitVCS_GIT = is_git || !is_in_a_or_a_working_copy;

    bool canRabbitVCS_MERCURIAL = is_mercurial || !is_in_a_or_a_working_copy;

    bool canInitializeRepository = is_dir && !is_in_a_or_a_working_copy;

    bool canClone = canInitializeRepository;

    bool canPush = is_git || is_mercurial;

    bool canBranches = is_git;

    bool canTags = is_git;

    bool canRemotes = is_git;

    bool canClean = is_git;

    bool canReset = is_git;

    auto canStageFunc = [&]()->bool{
        if (is_git) {
            if (is_dir && is_in_a_or_a_working_copy) {
                return true;
            } else {
                if (!is_dir && is_in_a_or_a_working_copy && !is_versioned) {
                    return true;
                }
            }
        }
        return false;
    };
    bool canStage = canStageFunc();

    auto canUnstageFunc = [&]()->bool{
        if (is_git) {
            if (is_dir && is_in_a_or_a_working_copy) {
                return true;
            } else {
                if (!is_dir && is_in_a_or_a_working_copy && is_added) {
                    return true;
                }
            }
        }
        return false;
    };
    bool canUnstage = canUnstageFunc();

    bool canEditConflicts = is_in_a_or_a_working_copy && is_versioned && is_conflicted;

    /*
     * \"is_svn\": false, \"is_git\": false, \"is_mercurial\": false, \"is_dir\": true,
     * \"is_file\": false, \"exists\": true, \"is_working_copy\": false, \"is_in_a_or_a_working_copy\": false,
     * \"is_versioned\": false, \"is_normal\": false, \"is_added\": false, \"is_modified\": false, \"is_deleted\": false,
     * \"is_ignored\": false, \"is_locked\": false, \"is_missing\": false, \"is_conflicted\": false, \"is_obstructed\": false,
     * \"has_unversioned\": false, \"has_added\": false, \"has_modified\": false, \"has_deleted\": false, \"has_ignored\": false,
     * \"has_missing\": false, \"has_conflicted\": false, \"has_obstructed\": false
     */


    switch (vcs_module) {
    case VCS_SVN: {
        auto svnMenu = new QMenu;
        menu = svnMenu;
        auto checkoutAction = svnMenu->addAction(QObject::tr("Checkout"), [=]{
            doCheckOut(paths);
        });
        checkoutAction->setVisible(canCheckout);
        // 菜单
        auto diffMenuAction = svnMenu->addAction(QObject::tr("Diff Menu"));
        diffMenuAction->setMenu(getDiffSubMenu(paths, trueList));
        diffMenuAction->setVisible(canDiffMenu);

        auto showLogAction = svnMenu->addAction(QObject::tr("Show Log"), [=]{
            doShowLog(paths);
        });
        showLogAction->setVisible(canShowLog);
        auto repoBrowserAction = svnMenu->addAction(QObject::tr("Repo Browser"), [=]{
            executeCommand("browser", QStringList()<<paths.first());
        });
        repoBrowserAction->setVisible(canRepoBrowser);
        auto checkForModificationAction = svnMenu->addAction(QObject::tr("Check for Modification"), [=]{
            doCheckForModification(paths);
        });
        checkForModificationAction->setVisible(canCheckForModification);
        auto separator1 = svnMenu->addSeparator();
        auto addAction = svnMenu->addAction(QObject::tr("Add"), [=]{
            doAdd(paths);
        });
        addAction->setVisible(canAdd);
        auto addToIgnoreListAction = svnMenu->addAction(QObject::tr("Add to Ignore List"), [=]{
            //FIXME
            executeCommand("ignore", paths);
        });
        addToIgnoreListAction->setVisible(canAddToIgnoreList);
        auto separator2 = svnMenu->addSeparator();
        auto updateToReversionAction = svnMenu->addAction(QObject::tr("Update to Reversion"), [=]{
            doUpdateToReversion(paths);
        });
        updateToReversionAction->setVisible(canUpdateToReversion);
        auto renameAction = svnMenu->addAction(QObject::tr("Rename"), [=]{
            doRename(paths);
        });
        renameAction->setVisible(canRename);
        auto deleteAction = svnMenu->addAction(QObject::tr("Delete"), [=]{
            doDelete(paths);
        });
        deleteAction->setVisible(canDelete);
        auto revertAction = svnMenu->addAction(QObject::tr("Revert"), [=]{
            doRevert(paths);
        });
        revertAction->setVisible(canRevert);
        auto editConflictsAction = svnMenu->addAction(QObject::tr("Edit Conflicts"), [=]{
            doEditConflicts(paths);
        });
        editConflictsAction->setVisible(canEditConflicts);
        auto markResolvedAction = svnMenu->addAction(QObject::tr("Mark Resolved"), [=]{
            doMarkResolved(paths);
        });
        markResolvedAction->setVisible(canMarkResolved);
        auto relocateAction = svnMenu->addAction(QObject::tr("Relocate"), [=]{
            doRelocate(paths);
        });
        relocateAction->setVisible(canRelocate);
        auto getLockAction = svnMenu->addAction(QObject::tr("Get Lock"), [=]{
            doGetLock(paths);
        });
        getLockAction->setVisible(canGetLock);
        auto unlockAction = svnMenu->addAction(QObject::tr("Unlock"), [=]{
            doUnlock(paths);
        });
        unlockAction->setVisible(canUnlock);
        auto cleanUpAction = svnMenu->addAction(QObject::tr("Clean Up"), [=]{
            doCleanUp(paths);
        });
        cleanUpAction->setVisible(canCleanUp);
        auto separator3 = svnMenu->addSeparator();
        auto svnExportAction = svnMenu->addAction(QObject::tr("SVN Export"), [=]{
            doSVNExport(paths);
        });
        svnExportAction->setVisible(canSVNExport);
        auto createRepositoryAction = svnMenu->addAction(QObject::tr("Create Repository"), [=]{
            doCreateRepository(paths);
        });
        createRepositoryAction->setVisible(canCreateRepository);
        auto importAction = svnMenu->addAction(QObject::tr("Import"), [=]{
            doImport(paths);
        });
        importAction->setVisible(canImport);
        auto separator4 = svnMenu->addSeparator();
        auto branchTagAction = svnMenu->addAction(QObject::tr("Branch Tag"), [=]{
            doBranchTag(paths);
        });
        branchTagAction->setVisible(canBranchTag);
        auto switchAction = svnMenu->addAction(QObject::tr("Switch"), [=]{
            doSwitch(paths);
        });
        switchAction->setVisible(canSwitch);
        auto mergeAction = svnMenu->addAction(QObject::tr("Merge"), [=]{
            doMerge(paths);
        });
        mergeAction->setVisible(canMerge);
        auto separator5 = svnMenu->addSeparator();
        auto createPatchAction = svnMenu->addAction(QObject::tr("Create Patch"), [=]{
            doCreatePatch(paths);
        });
        createPatchAction->setVisible(canCreatePatch);
        auto applyPatchAction = svnMenu->addAction(QObject::tr("Apply Patch"), [=]{
            doApplyPatch(paths);
        });
        applyPatchAction->setVisible(canApplyPatch);
        auto propertiesAction = svnMenu->addAction(QObject::tr("Properties"), [=]{
            doProperties(paths);
        });
        propertiesAction->setVisible(canProperties);
        auto separator6 = svnMenu->addSeparator();
        auto settingsAction = svnMenu->addAction(QObject::tr("settings"), [=]{
            executeCommand("settings", QStringList());
        });
        auto aboutAction = svnMenu->addAction(QObject::tr("About"), [=]{
            executeCommand("about", QStringList());
        });

        /*
         * (MenuUpdate, None),
            (MenuCommit, None),
            (MenuPush, None),
            None if settings.get("HideItem", "svn") else (MenuRabbitVCSSvn, [
                (MenuCheckout, None),
                (MenuDiffMenu, [
                    (MenuDiff, None),
                    (MenuDiffPrevRev, None),
                    (MenuDiffMultiple, None),
                    (MenuCompareTool, None),
                    (MenuCompareToolPrevRev, None),
                    (MenuCompareToolMultiple, None),
                    (MenuShowChanges, None),
                ]),
                (MenuShowLog, None),
                (MenuRepoBrowser, None),
                (MenuCheckForModifications, None),
                (MenuSeparator, None),
                (MenuAdd, None),
                (MenuAddToIgnoreList, ignore_items),
                (MenuSeparator, None),
                (MenuUpdateToRevision, None),
                (MenuRename, None),
                (MenuDelete, None),
                (MenuRevert, None),
                (MenuEditConflicts, None),
                (MenuMarkResolved, None),
                (MenuRelocate, None),
                (MenuGetLock, None),
                (MenuUnlock, None),
                (MenuCleanup, None),
                (MenuSeparator, None),
                (MenuSVNExport, None),
                (MenuCreateRepository, None),
                (MenuImport, None),
                (MenuSeparator, None),
                (MenuBranchTag, None),
                (MenuSwitch, None),
                (MenuMerge, None),
                (MenuSeparator, None),
                (MenuAnnotate, None),
                (MenuSeparator, None),
                (MenuCreatePatch, None),
                (MenuApplyPatch, None),
                (MenuProperties, None),
                (MenuSeparator, None),
                (MenuSettings, None),
                (MenuAbout, None)
         */
        break;
    }
    case VCS_GIT: {
        auto gitMenu = new QMenu;
        menu = gitMenu;

        auto cloneAction = gitMenu->addAction(QObject::tr("Clone"), [=]{
            doClone(paths);
        });
        cloneAction->setVisible(canClone);
        auto initAction = gitMenu->addAction(QObject::tr("Initialize Repository"), [=]{
            executeCommand("create", QStringList()<<"--vcs"<<"git"<<paths);
        });
        initAction->setVisible(canInitializeRepository);
        auto sperator1 = gitMenu->addSeparator();
        // 菜单
        auto diffMenuAction = gitMenu->addAction(QObject::tr("DiffMenu"));
        diffMenuAction->setMenu(getDiffSubMenu(paths, trueList));
        diffMenuAction->setVisible(canDiffMenu);

        auto showLogAction = gitMenu->addAction(QObject::tr("Show Log"), [=]{
            doShowLog(paths);
        });
        showLogAction->setVisible(canShowLog);
        auto stageAction = gitMenu->addAction(QObject::tr("Stage"), [=]{
            doStage(paths);
        });
        stageAction->setVisible(canStage);
        auto unStageAction = gitMenu->addAction(QObject::tr("Unstage"), [=]{
            doUnstage(paths);
        });
        unStageAction->setVisible(canUnstage);
        auto addToIgnoreListAction = gitMenu->addAction(QObject::tr("Add to Ignore List"), [=]{
            executeCommand("ignore", paths);
        });
        addToIgnoreListAction->setVisible(canAddToIgnoreList);
        auto separator2 = gitMenu->addSeparator();
        auto renameAction = gitMenu->addAction(QObject::tr("Rename"), [=]{
            doRename(paths);
        });
        renameAction->setVisible(canRename);
        auto deleteAction = gitMenu->addAction(QObject::tr("Delete"), [=]{
            doDelete(paths);
        });
        deleteAction->setVisible(canDelete);
        auto revertAction = gitMenu->addAction(QObject::tr("Revert"), [=]{
            doRevert(paths);
        });
        revertAction->setVisible(canRevert);
        auto cleanAction = gitMenu->addAction(QObject::tr("Clean"), [=]{
            doClean(paths);
        });
        cleanAction->setVisible(canClean);
        auto resetAction = gitMenu->addAction(QObject::tr("Reset"), [=]{
            doReset(paths);
        });
        resetAction->setVisible(canReset);
        auto checkOutAction = gitMenu->addAction(QObject::tr("Checkout"), [=]{
            doCheckOut(paths);
        });
        checkOutAction->setVisible(canCheckout);
        auto separator3 = gitMenu->addSeparator();
        auto branchesAction = gitMenu->addAction(QObject::tr("Branches"), [=]{
            doBranches(paths);
        });
        branchesAction->setVisible(canBranches);
        auto tagsAction = gitMenu->addAction(QObject::tr("Tags"), [=]{
            doTags(paths);
        });
        tagsAction->setVisible(canTags);
        auto remotesAction = gitMenu->addAction(QObject::tr("Remotes"), [=]{
            doRemotes(paths);
        });
        remotesAction->setVisible(canRemotes);
        auto separator4 = gitMenu->addSeparator();
        auto gitExportAction = gitMenu->addAction(QObject::tr("Git Export"), [=]{
            doGitExport(paths);
        });
        gitExportAction->setVisible(canGitExport);
        auto mergeAction = gitMenu->addAction(QObject::tr("Merge"), [=]{
            doMerge(paths);
        });
        mergeAction->setVisible(canMerge);
        auto separator5 = gitMenu->addSeparator();
        auto annotateAction = gitMenu->addAction(QObject::tr("Annotate"), [=]{
            doAnnotate(paths);
        });
        annotateAction->setVisible(canAnnotate);
        auto separator6 = gitMenu->addSeparator();
        auto createPatch = gitMenu->addAction(QObject::tr("Create Patch"), [=]{
            doCreatePatch(paths);
        });
        createPatch->setVisible(canCreatePatch);
        auto applyPatch = gitMenu->addAction(QObject::tr("Apply Patch"), [=]{
            doApplyPatch(paths);
        });
        applyPatch->setVisible(canApplyPatch);
        auto separator7 = gitMenu->addSeparator();
        auto settingsAction = gitMenu->addAction(QObject::tr("Settings"), [=]{
            executeCommand("settings", QStringList());
        });
        auto aboutAction = gitMenu->addAction(QObject::tr("About"), [=]{
            executeCommand("about", QStringList());
        });
            /*
             * (MenuClone, None),
                (MenuInitializeRepository, None),
                (MenuSeparator, None),
                (MenuDiffMenu, [
                    (MenuDiff, None),
                    (MenuDiffPrevRev, None),
                    (MenuDiffMultiple, None),
                    (MenuCompareTool, None),
                    (MenuCompareToolPrevRev, None),
                    (MenuCompareToolMultiple, None),
                    (MenuShowChanges, None),
                ]),
                (MenuShowLog, None),
                (MenuStage, None),
                (MenuUnstage, None),
                (MenuAddToIgnoreList, ignore_items),
                (MenuSeparator, None),
                (MenuRename, None),
                (MenuDelete, None),
                (MenuRevert, None),
                (MenuClean, None),
                (MenuReset, None),
                (MenuCheckout, None),
                (MenuSeparator, None),
                (MenuBranches, None),
                (MenuTags, None),
                (MenuRemotes, None),
                (MenuSeparator, None),
                (MenuGitExport, None),
                (MenuMerge, None),
                (MenuSeparator, None),
                (MenuAnnotate, None),
                (MenuSeparator, None),
                (MenuCreatePatch, None),
                (MenuApplyPatch, None),
                (MenuSeparator, None),
                (MenuSettings, None),
                (MenuAbout, None)
             */
        break;
    }
    default: {
        auto hgMenu = new QMenu;
        menu = hgMenu;
        hgMenu->addAction(QObject::tr("Settings"), [=]{
            executeCommand("settings", QStringList());
        });
        hgMenu->addAction(QObject::tr("About"), [=]{
            executeCommand("about", QStringList());
        });
        break;
    }
    }

    return menu;
}

QList<QAction *> RabbitVCSMenuHelper::getActionsFromConditions(const QStringList &paths, const QString &conditions)
{
    QList<QAction *> l;

    auto trueList = getTrueLists(conditions);
    qDebug()<<trueList;

    bool is_git = trueList.contains("is_git");
    bool is_svn = trueList.contains("is_svn");
    bool is_mercurial = trueList.contains("is_mercurial");
    bool is_dir = trueList.contains("is_dir");
    bool is_deleted = trueList.contains("is_deleted");
    bool is_modified = trueList.contains("is_modified");
    bool is_in_a_or_a_working_copy = trueList.contains("is_in_a_or_a_working_copy");
    bool is_versioned = trueList.contains("is_versioned");
    bool is_added = trueList.contains("is_added");


    bool canUpdate = is_in_a_or_a_working_copy && is_versioned && !is_added;
    auto canCommitFunc = [&]()->bool{
        if (is_svn || is_git || is_mercurial) {
            if (is_in_a_or_a_working_copy) {
                if (is_added || is_modified || is_deleted || !is_versioned) {
                    return true;
                } else {
                    if (is_dir) {return true;}
                }
            }
        }
        return false;
    };
    bool canCommit = canCommitFunc();
    bool canPush = is_git || is_mercurial;
    bool canRabbitVCS_SVN = is_svn || !is_in_a_or_a_working_copy;
    bool canRabbitVCS_GIT = is_git || !is_in_a_or_a_working_copy;
    bool canRabbitVCS_MERCURIAL = is_mercurial || !is_in_a_or_a_working_copy;
    // 更新选项
    auto updateAction = new QAction(QObject::tr("Update"));
    QObject::connect(updateAction, &QAction::triggered, updateAction, [=]{
        executeCommand("update", paths);
    });
    updateAction->setVisible(canUpdate);
    l<<updateAction;

    // 提交选项
    auto commitAction = new QAction(QObject::tr("Commit"));
    QObject::connect(commitAction, &QAction::triggered, commitAction, [=]{
        executeCommand("commit", paths);
    });
    commitAction->setVisible(canCommit);
    l<<commitAction;

    // 推送选项
    auto pushAction = new QAction(QObject::tr("Push"));
    QObject::connect(pushAction, &QAction::triggered, pushAction, [=]{
        executeCommand("push", paths);
    });
    pushAction->setVisible(canPush);
    l<<pushAction;

    if (canRabbitVCS_SVN) {
        // SVN子菜单
        auto svnAction = new QAction(QObject::tr("RabbitVCS SVN"));
        auto svnMenu = getMainContextSubMenu(VCS_SVN, paths, trueList);
        svnAction->setMenu(svnMenu);
        l<<svnAction;
    }

    if (canRabbitVCS_GIT) {
        // Git子菜单
        auto gitAction = new QAction(QObject::tr("RabbitVCS Git"));
        auto gitMenu = getMainContextSubMenu(VCS_GIT, paths, trueList);
        gitAction->setMenu(gitMenu);
        l<<gitAction;
    }

    if (canRabbitVCS_MERCURIAL) {
        // HG子菜单
        auto hgAction = new QAction(QObject::tr("RabbitVCS Hg"));
        auto hgMenu = getMainContextSubMenu(VCS_HG, paths, trueList);
        hgAction->setMenu(hgMenu);
        l<<hgAction;
    }

    if (l.count() > 0) {
        l.prepend(createSeparator());
        l.append(createSeparator());
    }

    return l;
}

RabbitVCSMenuHelper::RabbitVCSMenuHelper()
{

}
